package org.road0329.tools.proto_parse_tool.chargingpile;

import org.road0329.tools.proto_parse_tool.chargingpile.busi.AuthResult;
import org.road0329.tools.proto_parse_tool.chargingpile.busi.DataPileMonitor;
import org.road0329.tools.proto_parse_tool.chargingpile.busi.StopChargeResult;
import org.road0329.tools.proto_parse_tool.enums.CmdHighEnum;
import org.road0329.tools.proto_parse_tool.enums.CmdLowEnum;
import org.road0329.tools.proto_parse_tool.enums.PileCmdEnum;
import org.road0329.tools.proto_parse_tool.utils.ProtocolUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class ProtocolJuhuaHandle {
    private static final short SUCCESS = 1; //成功
    private static final short DAY_MINUTES = 1440; //一天的分钟数
    private static final short FLAG_SUCCESS = (short) 1; //鉴权成功
    private static final short FLAG_FAIL = (short) 0; //鉴权失败
    private static final short CARD_STATUS_FORBIDDEN = 2;// 卡 禁用
    private static final short CARD_STATUS_CLOSE = 3;// 销卡

    private static final short CHARGE_WAY_WALLET = 1; //电子钱包
    private static final short CHARGE_WAY_QR_CODE = 3; // 二维码
    private static final short CHARGE_WAY_LINE_CONNECT = 5; // 连接电缆线充电
    private static final short CHARGE_WAY_CARD_ONLINE = 2; //有卡在线
    private static final short CHARGE_WAY_CARD_DOOR = 4; //门禁卡

    private static final short ACCOUNT_STATUS_NORAML = 1; //正常

    private static final int AMOUNT_FREEZE = 200 * 100;//200元 单位：分

    private static final int BLOCK_SIZE = 256;//默认大小

    private static final String CARD_NO_PREFIX_QR_CODE = "300360";

    private static final String CARD_NO_PREFIX_INTERFACE = "360360";

    private static final String FLAG_INTERFACE = "Interface"; //接口标识

    private static final short CHARGE_TYPE_ONE2ONE = 1;//一卡一充

    private static final short SETTLE_ENABLE = 1;//允许结算

    public static BaseFrame validateMessage(byte[] msg) {
        byte head = msg[0];
        if ((head & 0xff) != 0xF8) {
            return null;
        }
        int addr = msg[1];
        byte high = msg[2];
        byte low = msg[3];
        short len = ProtocolUtils.byteToShort(low, high);
        if (msg.length < len + 2) {
            return null;
        }

        // 帧尾校验
        if (msg[msg.length - 1] != 0x0D) {
            return null;
        }

        BaseFrame frame = new BaseFrame(msg, len);
        int index = 6;
        String commAddr = ProtocolUtils.getStringByBCD(msg, index, 8);
        frame.setCommAddr(commAddr);
        frame.setCmdType(msg[4]);
        if (msg[4] > 0x20 && msg[4] < 0x46) {
            frame.setGunNo((int) msg[index + 8]);
        }
        return frame;
    }

    public static MsgDcsResult decoder(BaseFrame frame) {
        byte[] msg = frame.getData();
        // cmd
        byte cmdLow = msg[4];
        byte cmdHigh = msg[5];
        if (CmdHighEnum.WEB.getValue() == cmdHigh) {
            //logger.warn("同端的消息无需处理");
            return null;
        }
        ChargingPile pile = new ChargingPile();
        pile.setPileId(frame.getPileId());
        pile.setEid(frame.getEid());
        pile.setCode(frame.getCommAddr());
        Integer gunNo = frame.getGunNo();
        if (gunNo != null) {
            pile.setGunNo(gunNo);
        }
        Object param = pile;

        int contentLength = frame.getLength() - 2;
        byte[] content = new byte[contentLength];
        System.arraycopy(msg, 6, content, 0, contentLength);

        MsgDcsResult result = null;
        try {
            if (CmdLowEnum.PILE_INIT.getValue() == cmdLow) {
                result = parsePileInit(msg);
            } else if (CmdLowEnum.CARD_VALIDATE.getValue() == cmdLow) {
                result = parseCardValidate(msg);
            } else if (CmdLowEnum.CHARGE_AUTHEN.getValue() == cmdLow) {
                result = parseChargeAuthenReply(msg);
            } else if (CmdLowEnum.CHARGE_AUTHEN_PLUG.getValue() == cmdLow) {

                result = parseChargeAuthenReply(msg);
            } else if (CmdLowEnum.CHARGE_RECORD.getValue() == cmdLow || CmdLowEnum.CHARGE_RECORD_HZMSJL.getValue() == cmdLow) {
                result = parseChargeRecord(cmdLow, msg);
                ChargeRecord record = (ChargeRecord) result.getData();
                ChargeRecordReply chargeRecordReply = new ChargeRecordReply();
                chargeRecordReply.setCode(record.getCode());
                chargeRecordReply.setGunNo(record.getGunNo());
                chargeRecordReply.setCardNo(record.getCardNo());
                chargeRecordReply.setTradeNo(record.getTradeNo());
                BigDecimal totalFee = record.getTotalFee();
                if (totalFee == null) {
                    totalFee = BigDecimal.ZERO;
                }
                totalFee = totalFee.multiply(BigDecimal.valueOf(100));
                chargeRecordReply.setAmount(totalFee.intValue());
                chargeRecordReply.setFlag(FLAG_SUCCESS);
                BigDecimal afterMoney = record.getWalletAfterMoney();
                if (afterMoney == null) {
                    afterMoney = BigDecimal.ZERO;
                }
                afterMoney = afterMoney.multiply(BigDecimal.valueOf(100));
                chargeRecordReply.setBalance(afterMoney.intValue());

                param = chargeRecordReply;
            } else if (CmdLowEnum.STATE_CHANGE.getValue() == cmdLow) {
                result = parseStateChange(msg);
            } else if (CmdLowEnum.HEART_BEAT.getValue() == cmdLow) {
                result = parseHeartBeat(msg);
            } else if (CmdLowEnum.AC_MONITOR.getValue() == cmdLow || CmdLowEnum.AC_MONITOR_EX.getValue() == cmdLow
                    || CmdLowEnum.AC_MONITOR_HZMSJL.getValue() == cmdLow) {
                result = parseAcPileMonitorData(cmdLow, msg);
            } else if (CmdLowEnum.DC_MONITOR.getValue() == cmdLow || CmdLowEnum.DC_MONITOR_HZMSJL.getValue() == cmdLow) {
                result = parseDcPileMonitorData(cmdLow, msg);
            } else if (CmdLowEnum.DC_TEMPERATURE.getValue() == cmdLow) {
                result = parseDcTemperature(msg);
            } else if (CmdLowEnum.REQUEST_QR.getValue() == cmdLow) {
                result = parseRequestQr(msg);
            } else if (CmdLowEnum.REQUEST_UPGRADE_DATAPACK.getValue() == cmdLow) {
                result = parseRequestUpgradeDataPack(msg);
            } else if (CmdLowEnum.SEND_SUMMARY.getValue() == cmdLow) {
                result = parseSendSummary(msg);
            } else if (CmdLowEnum.STOP_CHARGE.getValue() == cmdLow
                    || CmdLowEnum.SETUP_QR.getValue() == cmdLow
                    || CmdLowEnum.PRICE_MODEL.getValue() == cmdLow) {
                result = parsePileRegularReply(msg);
                PileRegularReply reply = (PileRegularReply) result.getData();
                if (CmdLowEnum.STOP_CHARGE.getValue() == cmdLow) {
                    StopChargeResult stopChargeResult = new StopChargeResult();
                    stopChargeResult.setCommAddr(reply.getCode());
                    stopChargeResult.setGunNo(reply.getGunNo());
                    stopChargeResult.setSuccess(reply.getFlag() == SUCCESS);
                    result.setData(stopChargeResult);
                }
            } else {
                return null;
            }
            if (result.getData() instanceof ChargingPile) {
                ChargingPile tmpPile = (ChargingPile) result.getData();
                result.setGunNo(tmpPile.getGunNo());
            }
            result.setSuccess(true);
            result.setCmdType(convertTaskType(cmdLow, result.getData()));
        } catch (Exception e) {
            result = new MsgDcsResult();
            result.setSuccess(false);
            result.setMessage("命令解析出错:" + e.getMessage());
        }

        return result;
    }

    private static int convertTaskType(int taskType, Object data) {
        if (taskType == CmdLowEnum.CHARGE_AUTHEN.getValue()) {
            return PileCmdEnum.AUTH.getValue();
        } else if (taskType == CmdLowEnum.STOP_CHARGE.getValue()) {
            return PileCmdEnum.STOP_CHARGE.getValue();
        } else if (taskType == CmdLowEnum.PRICE_MODEL.getValue()) {
            return PileCmdEnum.PRICE_SET.getValue();
        } else if (taskType == CmdLowEnum.SEND_SUMMARY.getValue()) {
            return PileCmdEnum.ONLINE_UPDATE.getValue();
        } else if (taskType == CmdLowEnum.SETUP_QR.getValue()) {
            return PileCmdEnum.PILE_QR_CODE_SET.getValue();
        } else if (taskType == CmdLowEnum.UPDATE_PILE_PARAM.getValue()) {
            if (!(data instanceof PileParam)) {
                return -1;
            }
            PileParam pileParam = (PileParam) data;
            data = pileParam.getParam();
            if (data instanceof PileParamServer) {
                return PileCmdEnum.PILE_SERVER_SET.getValue();
            } else if (data instanceof PileParamCode) {
                return PileCmdEnum.PILE_NO_SET.getValue();
            } else if (data instanceof PileParamNetwork) {
                return PileCmdEnum.PILE_NO_SET.getValue();
            }
        }
        return -1;
    }

    private static MsgDcsResult parsePileParamServer(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        PileParam param = new PileParam();
        PileParamServer paramServer = new PileParamServer();
        param.setParam(paramServer);
        result.setData(param);

        int index = 6; //帧头
        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        param.parseCode(pileCode);
        index += 8; //桩编号

        param.setFrameType(msg[index]);
        index++;

        paramServer.setIp(ProtocolUtils.ascii2String(msg, index, 15));
        index += 15;

        paramServer.setPort(ProtocolUtils.ascii2String(msg, index, 4));
        index += 4;

        return result;
    }

    private static MsgDcsResult parsePileParamCode(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        PileParamCode param = new PileParamCode();
        result.setData(param);

        int index = 6; //帧头
        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        param.parseCode(pileCode);
        index += 8; //桩编号

        param.setFrameType(msg[index]);
        index++;

        param.setCode(ProtocolUtils.getStringByBCD(msg, index, 8));
        index++;

        param.setStationAddr(ProtocolUtils.byteToShort(msg[index], msg[index++]));
        index += 2;

        param.setCommMode(msg[index]);
        index++;

        param.setEnableQr(msg[index]);
        index++;

        return result;
    }

    public static MsgDcsResult parseDcTemperature(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        PileTemperature temperature = new PileTemperature();
        result.setData(temperature);

        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        temperature.parseCode(pileCode);
        index += 8; //桩编号

        short moduleNum = msg[index];
        temperature.setModuleNum(moduleNum);
        index++;
        if (moduleNum <= 0) {
            return result;
        }

        List<ModuleTemperature> temperatureList = new ArrayList<>(moduleNum);
        temperature.setModuleTemperatureList(temperatureList);
        ModuleTemperature moduleTemp;
        for (int i = 0; i < moduleNum; i++) {
            moduleTemp = new ModuleTemperature();
            moduleTemp.setEnvTemp(msg[index]);
            index++;
            moduleTemp.setDmosTemp(msg[index]);
            index++;
            moduleTemp.setPmosTmep(msg[index]);
            index++;
            moduleTemp.setOutputRectifierTemp(msg[index]);
            index++;

            temperatureList.add(moduleTemp);
        }

        return result;
    }

    public static MsgDcsResult parseCardValidate(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        CardValidate validate = new CardValidate();
        result.setData(validate);

        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        validate.parseCode(pileCode);
        index += 8; //桩编号

        validate.parseGunNo(msg[index]);
        index += 1; //枪号

        validate.setCardNo(ProtocolUtils.getStringByBCD(msg, index, 8));
        index += 8;

        byte[] password = new byte[8];
        System.arraycopy(msg, index, password, 0, 8);
        //密码解密
//        password = DESUtil.convertHex2Bin(password);
//        password = DES.decrypt(password, DES_KEY);
//        password = DESUtil.convertBin2Hex(password);

        validate.setPassword(ProtocolUtils.getByteToHexString(password, 0, password.length, ""));

        return result;
    }

    public static MsgDcsResult parseChargeAuthenReply(byte[] msg) {
        ChargeAuthenReply reply = new ChargeAuthenReply();
        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        reply.parseCode(pileCode);
        index += 8; //桩编号

        reply.parseGunNo(msg[index]);
        index += 1; //枪号

        reply.setTradeNo(ProtocolUtils.getStringByBCD(msg, index, 16));
        index += 16;

        reply.setFlag(msg[index]);

        AuthResult authResult = new AuthResult();
        authResult.setCommAddr(reply.getCode());
        authResult.setGunNo(reply.getGunNo());
        authResult.setSuccess(reply.getFlag() == SUCCESS);
        authResult.setTradeNo(reply.getTradeNo());
        MsgDcsResult result = new MsgDcsResult();
        result.setData(authResult);
        return result;
    }

    private static MsgDcsResult parsePilePriceModelReply(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        PilePriceModelReply reply = new PilePriceModelReply();
        result.setData(reply);

        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        reply.parseCode(pileCode);
        index += 8; //桩编号

        reply.parseGunNo(msg[index]);
        index += 1; //枪号

        reply.setVersion(ProtocolUtils.byteToShort(msg[index], msg[index + 1]));
        index += 2;

        reply.setFlag(msg[index]);
        return result;
    }

    public static MsgDcsResult parseStateChange(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        PileStateChange change = new PileStateChange();
        result.setData(change);
        int index = 6;//帧头
        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        change.parseCode(pileCode);
        index += 8;//桩编号

        change.setGunNo(msg[index]);
        index += 1; //枪号

        change.setStatus(ProtocolUtils.byteToShort(msg[index + 1], msg[index]));
        index += 2;
        change.setFaultCode(String.format("%02X%02X%02X%02X%02X%02X%02X%02X", msg[index], msg[index + 1], msg[index + 2], msg[index + 3], msg[index + 4], msg[index + 5], msg[index + 6], msg[index + 7]));
        return result;
    }

    public static MsgDcsResult parseAcPileMonitorData(byte cmdLow, byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        AcPileMonitorData data = new AcPileMonitorData();
        result.setData(data);
        int index = 6; //帧头
        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        data.parseCode(pileCode);
        index += 8;//桩编号

        data.setGunNo(msg[index]);
        index += 1; //枪号

        data.setSwitchStatus(msg[index]);
        index++;
        data.setStatus(ProtocolUtils.byteToShort(msg[index + 1], msg[index]));
        index += 2;

        index += 8; //告警
        data.setU(ProtocolUtils.byteToFloat(msg[index + 1], msg[index], 1));
        index += 2;

        data.setI(ProtocolUtils.byteToFloat(msg[index + 1], msg[index], 2));
        index += 2;

        data.setRelayStatus(msg[index]);
        index++;

        int energyScale = 2; //电量精度
        if (CmdLowEnum.AC_MONITOR_HZMSJL.getValue() == cmdLow) {
            energyScale = 3;
        }
        data.setCumulant(ProtocolUtils.byteToDouble(msg, index, energyScale));
        index += 4;

        data.setChargeLen(ProtocolUtils.byteToShort(msg[index + 1], msg[index]));

        return result;
    }

    public static MsgDcsResult parseDcPileMonitorData(byte cmdLow, byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        DcPileMonitorData data = new DcPileMonitorData();
        result.setData(data);
        int index = 6; //帧头
        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        data.parseCode(pileCode);
        index += 8;//桩编号

        data.setGunNo(msg[index]);
        index += 1; //枪号

        int energyScale = 2; //电量精度
        if (CmdLowEnum.DC_MONITOR_HZMSJL.getValue() == cmdLow) {
            energyScale = 3;
        }

        data.setStatus(ProtocolUtils.byteToShort(msg[index + 1], msg[index]));
        index += 2;
        data.setConnect(msg[index]);
        index++;

        data.setChargeLen(ProtocolUtils.byteToShort(msg[index + 1], msg[index]));
        index += 2;

        data.setCumulant(ProtocolUtils.byteToDouble(msg, index, energyScale));
        index += 4;

        data.setU(ProtocolUtils.byteToFloat(msg[index + 1], msg[index], 1));
        index += 2;

        data.setI(ProtocolUtils.byteToFloat(msg[index + 1], msg[index], 2));
        index += 2;

        data.setSoc(ProtocolUtils.byteToShort(msg[index + 1], msg[index]));
        index += 2;

        data.setBatteryPackTempMin(ProtocolUtils.byteToSignFloat(msg[index + 1], msg[index], 1));
        index += 2;

        data.setBatteryPackTempMax(ProtocolUtils.byteToSignFloat(msg[index + 1], msg[index], 1));
        index += 2;

        data.setBatteryUMax(ProtocolUtils.byteToSignFloat(msg[index + 1], msg[index], 2));
        index += 2;

        data.setBatteryUMin(ProtocolUtils.byteToSignFloat(msg[index + 1], msg[index], 2));
        index += 2;

        data.setDcPosTemp(ProtocolUtils.byteToSignFloat(msg[index + 1], msg[index], 1));
        index += 2;

        data.setDcNegTemp(ProtocolUtils.byteToSignFloat(msg[index + 1], msg[index], 1));
        index += 2;

        data.setFaultCode(String.format("%02x%02x", msg[index++], msg[index++]));

//        index += 17;//汽车VIN号
        data.setModuleTotalNum((short) (msg[index++] & 0xff));
        data.setModuleUsableNum((short) (msg[index++] & 0xff));
        data.setModuleHiddenNum((short) (msg[index++] & 0xff));

        data.setVehicleDemandI(ProtocolUtils.byteToFloat(msg[index + 1], msg[index], 1));
        index += 2;
        data.setVehicleDetectI(ProtocolUtils.byteToFloat(msg[index + 1], msg[index], 1));
        index += 2;
        data.setVehicleDetectU(ProtocolUtils.byteToFloat(msg[index + 1], msg[index], 1));
        index += 2;

        return result;
    }

    public static MsgDcsResult parseChargeRecord(byte cmdLow, byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        ChargeRecord record = new ChargeRecord();
        result.setData(record);

        int energyScale = 2; //电量精度
        if (CmdLowEnum.CHARGE_RECORD_HZMSJL.getValue() == cmdLow) {
            energyScale = 3;
        }

        int index = 6; //帧头
        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        record.parseCode(pileCode);
        index += 8;//桩编号

        record.setGunNo(msg[index]);
        index += 1; //枪号

        record.setTradeNo(ProtocolUtils.getStringByBCD(msg, index, 16));
        index += 16;

        record.setCardNo(ProtocolUtils.getStringByBCD(msg, index, 8));
        index += 8;

        record.setRecordType((short) msg[index]);
        index++;

        byte[] date = new byte[7];
        System.arraycopy(msg, index, date, 0, 7);
        record.setStartTime(ProtocolUtils.getDateByCP56Time2a(date));
        index += 7;

        date = new byte[7];
        System.arraycopy(msg, index, date, 0, 7);
        record.setEndTime(ProtocolUtils.getDateByCP56Time2a(date));
        index += 7;

        record.setStartCumulant(ProtocolUtils.byteToBigDecimal(msg, index, 4, energyScale));

        index += 4;

        record.setEndCumulant(ProtocolUtils.byteToBigDecimal(msg, index, 4, energyScale));
        index += 4;

        record.setTotalFee(ProtocolUtils.byteToBigDecimal(msg, index, 4, 2));
        index += 4;

        record.setChargeWay((short) msg[index]);
        index++;

        record.setCutStatus((short) msg[index]);
        index++;

        record.setWalletBeforeMoney(ProtocolUtils.byteToBigDecimal(msg, index, 4, 2));
        index += 4;

        record.setWalletAfterMoney(ProtocolUtils.byteToBigDecimal(msg, index, 4, 2));
        index += 4;

        record.setPriceVersion(Integer.valueOf(ProtocolUtils.byteToShort(msg[index + 1], msg[index])));
        index += 2;

        record.setEndChargeType((short) msg[index]);
        index++;

        record.setVin(ProtocolUtils.getByteToHexString(msg, index, 17, ""));
        index += 17;

        record.setBatteryType((short) msg[index]);
        index++;

        record.setBatteryCapacity(ProtocolUtils.byteToBigDecimal(msg, index, 2, 1));
        index += 2;

        record.setBatteryNominalU(ProtocolUtils.byteToBigDecimal(msg, index, 2, 1));
        index += 2;

        record.setAllowUMax(ProtocolUtils.byteToBigDecimal(msg, index, 2, 2));
        index += 2;

        record.setAllowIMax(ProtocolUtils.byteToBigDecimal(msg, index, 2, 1));
        index += 2;

        record.setBatteryTotalPower(ProtocolUtils.byteToBigDecimal(msg, index, 2, 2));
        index += 2;

        record.setAllowChargeUMax(ProtocolUtils.byteToBigDecimal(msg, index, 2, 1));
        index += 2;

        record.setAllowTempMax(BigDecimal.valueOf(msg[index]));
        index++;

        record.setStartSoc(msg[index] & 0xff);
        index++;

        record.setEndSoc(msg[index] & 0xff);
        index++;

        record.setChargeLen((int) ProtocolUtils.byteToShort(msg[index + 1], msg[index]));
        index += 2;

        record.setChargeEnergy(ProtocolUtils.byteToBigDecimal(msg, index, 4, energyScale));
        index += 4;

        int num = msg[index] & 0xff;
        index++;
        ChargeDetail chargeDetail = null;
        BigDecimal energy;
        for (int i = 0; i < num; i++) {
            chargeDetail = new ChargeDetail();
            date = new byte[7];
            System.arraycopy(msg, index, date, 0, 7);
            chargeDetail.setStartTime(ProtocolUtils.getDateByCP56Time2a(date));
            index += 7;
            date = new byte[7];
            System.arraycopy(msg, index, date, 0, 7);
            chargeDetail.setEndTime(ProtocolUtils.getDateByCP56Time2a(date));
            index += 7;
            energy = ProtocolUtils.byteToBigDecimal(msg, index, 4, energyScale);
            if (energy != null && energy.compareTo(BigDecimal.ZERO) < 0) {
                energy = BigDecimal.ZERO;
            }
            chargeDetail.setEnergy(energy);
            index += 4;
            chargeDetail.setTariffType((short) msg[index]);
            index++;

            record.addDetail(chargeDetail);
        }

        if (CmdLowEnum.CHARGE_RECORD_HZMSJL.getValue() == cmdLow ) {
            String version = ProtocolUtils.getByteToHexString(msg, index, 2, "");
            if("FFFF".equalsIgnoreCase(version) || "0000".equals(version)) {
                return  result;
            }
            MeterCiphertext meterCiphertext = new MeterCiphertext();
            meterCiphertext.setTradeNo(record.getTradeNo());
            meterCiphertext.setVersion(version);
            index += 2;
            meterCiphertext.setEncryptWay(ProtocolUtils.getStringByBCD(msg, index, 1));
            index++;
            meterCiphertext.setMeterNo(ProtocolUtils.getStringByBCD(msg, index, 6));
            index += 6;
            meterCiphertext.setCiphertext(ProtocolUtils.getByteToHexString(msg, index, 34, ""));
            record.setMeterCiphertext(meterCiphertext);
        }

        return result;
    }

    public static MsgDcsResult parseRequestUpgradeDataPack(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        RequestUpgradeDataPack requestUpgradeDataPack = new RequestUpgradeDataPack();
        result.setData(requestUpgradeDataPack);

        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        requestUpgradeDataPack.parseCode(pileCode);
        index += 8; //桩编号

        requestUpgradeDataPack.parseGunNo(msg[index]);
        index += 1; //枪号

        requestUpgradeDataPack.setDataPackIndex(ProtocolUtils.byteToShort(msg[index + 1], msg[index]));
        index += 2;

//        requestUpgradeDataPack.setResult(msg[index]);
        return result;
    }

    public static MsgDcsResult parseSendSummary(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        SendSummaryReply reply = new SendSummaryReply();
        result.setData(reply);

        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        reply.parseCode(pileCode);
        index += 8; //桩编号

        reply.parseGunNo(msg[index]);
        index += 1; //枪号

        reply.setHardwareVersion(ProtocolUtils.byteToShort(msg[index + 1], msg[index]));
        index += 2;

        reply.setSofewareVersion(ProtocolUtils.byteToShort(msg[index + 1], msg[index]));
        index += 2;

        reply.setReady(msg[index]);
        index++;

        reply.setReason(msg[index]);
        return result;
    }

    public static MsgDcsResult parseWorkingState(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        PileWorkingState state = new PileWorkingState();
        result.setData(state);

        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        state.parseCode(pileCode);
        index += 8; //桩编号

        state.parseGunNo(msg[index]);
        index += 1; //枪号

        state.setState(ProtocolUtils.byteToShort(msg[index + 1], msg[index]));
        return result;
    }

    public PileParamBody parseBodyParam(byte[] msg) {
        PileParamBody param = new PileParamBody();

        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        param.parseCode(pileCode);
        index += 8; //桩编号

        param.setType(msg[index]);
        index++;

        param.setStationAddr(ProtocolUtils.byteToShort(msg[index], msg[index++]));
        index += 2;

        param.setCommMode(msg[index]);
        index++;

        param.setEnableQr(msg[index]);
        index++;

        String ip = ProtocolUtils.ascii2String(msg, index, 15);
        param.setServerIp(ip);
        index += 15;

        int port = ProtocolUtils.byteToInteger(msg, index);
        param.setPort(port);
        index += 4;

        ip = ProtocolUtils.ascii2String(msg, index, 15);
        param.setPileIp(ip);
        index += 15;

        String subnetMask = ProtocolUtils.ascii2String(msg, index, 15);
        param.setPileSubnetMask(subnetMask);
        index += 15;

        String gateway = ProtocolUtils.ascii2String(msg, index, 15);
        param.setPileGateway(gateway);
        index += 15;

        return param;
    }

    public PileParamPasswordSecret parsePasswordSecret(byte[] msg) {
        PileParamPasswordSecret passwordSecret = new PileParamPasswordSecret();

        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        passwordSecret.parseCode(pileCode);
        index += 8; //桩编号

        passwordSecret.setPassword(ProtocolUtils.getStringByBCD(msg, index, 6));
        index += 6;

        passwordSecret.setSecret(ProtocolUtils.getByteToHexString(msg, index, 6, ""));
        index += 6;

        return passwordSecret;
    }

    public static MsgDcsResult parseHeartBeat(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        HeartBeat heartBeat = new HeartBeat();
        result.setData(heartBeat);

        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        heartBeat.parseCode(pileCode);
        index += 8; //桩编号

        heartBeat.parseGunNo(msg[index]);
        index += 1; //枪号

        return result;
    }

    public static MsgDcsResult parseRequestQr(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        RequestQr requestQr = new RequestQr();
        result.setData(requestQr);

        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        requestQr.parseCode(pileCode);
        index += 8; //桩编号

        requestQr.parseGunNo(msg[index]);
        index += 1; //枪号

        return result;
    }

    public static MsgDcsResult parsePileInit(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        PileInit init = new PileInit();
        result.setData(init);

        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        init.parseCode(pileCode);
        index += 8; //桩编号

        init.setStationAddr(ProtocolUtils.getStringByBCD(msg, 0, 2));
        index += 2; //站地址

        init.setProtocolVersion(ProtocolUtils.byteToShort(msg[index + 1], msg[index]));
        index += 2;

        init.setChargingModelVersion(ProtocolUtils.byteToShort(msg[index + 1], msg[index]));
        index += 2;

        init.setPileType(msg[index]);

        return result;
    }

    public static MsgDcsResult parsePileRegularReply(byte[] msg) {
        MsgDcsResult result = new MsgDcsResult();
        PileRegularReply reply = new PileRegularReply();
        result.setData(reply);

        int index = 6; //帧头

        byte[] pileCode = new byte[8];
        System.arraycopy(msg, index, pileCode, 0, 8);
        reply.parseCode(pileCode);
        index += 8; //桩编号

        reply.parseGunNo(msg[index]);
        index += 1; //枪号

        reply.setFlag(msg[index]);

        return result;
    }

    private void buildPileMonitor(AcPileMonitorData data) {
        //转换为DataPileMonitor

        Integer pileId = null;
        DataPileMonitor pileMonitor = new DataPileMonitor();
        pileMonitor.setPileId(pileId);
        pileMonitor.setGunNo(data.getGunNo());

        pileMonitor.setStatus(data.getStatus());

        pileMonitor.setU(BigDecimal.valueOf(data.getU()));
        pileMonitor.setI(BigDecimal.valueOf(data.getI()));
        pileMonitor.setRelayStatus(data.getRelayStatus());
        pileMonitor.setCumulant(BigDecimal.valueOf(data.getCumulant()));
        pileMonitor.setChargeLen(data.getChargeLen());
        Date now = new Date();
        pileMonitor.setAddTime(now);
    }
}
